# encoding=utf-8
"""
响应校验中间件
"""
import json
import logging
import threading
import time
from urllib.parse import quote
from scrapy.exceptions import IgnoreRequest
from abchina.util.aes_util import AesCrypter
from abchina.util.api_login import ApiLogin
from abchina.util.launcher import Launcher


class EncryptMiddleware(object):
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(EncryptMiddleware, "_instance"):
            with EncryptMiddleware._instance_lock:
                if not hasattr(EncryptMiddleware, "_instance"):
                    EncryptMiddleware._instance = object.__new__(cls)
        return EncryptMiddleware._instance

    def __init__(self):
        # init_cookies = {'GroupPurchaseSessionId': 'qc1p1lxejbr0mc1qgoc21mbc', 'security_session_verify': '9c81a706372ae772cf2bb1ac8e7e362b', 'BIGipServerpool_ebiz_qyjc': 'TEYtkQYPg49S8YdbBRrKEzfZ3SoIgH+IBgQUitNbXXlbXBbTsXtiValNBFLpNfc0KP4FTDnIg2Lh9N4='}
        # launcher = Launcher()
        # launcher.refresh_encrypt(init_cookies)
        # if launcher and launcher.sec_key and launcher.sec_iv:
        #     self.cookies = init_cookies
        #     self.sec_key = launcher.sec_key
        #     self.sec_iv = launcher.sec_iv
        # else:
        #     raise Exception('加密因子初始化失败')

        # TODO AUTO LOGIN
        # result = {'sec_key': 'dvHpFToYewOAQygrf7GiVktC3aM9X5E2', 'sec_iv': 'ej7HDOhGB56aoZnX', 'cookies': {'GroupPurchaseSessionId': 'rpjz1v5c55nzxoxjqr1m2oct', 'security_session_verify': '70721422b72a7e659ccffaf006d5ff3f', 'BIGipServerpool_ebiz_qyjc': '1894574858.21540.0000'}}
        # result = {"sec_key": "keTY0sowXDp6741fanBH52gvGNSUQKqu", "sec_iv": "ewX7l9uYHTy2zNDb", "cookies": {"BIGipServerpool_ebiz_qyjc": "4075809546.21540.0000", "GroupPurchaseSessionId": "rhulr5pkw0m0f3z4s042th2m"}}
        result = ApiLogin().get_encrypt_and_cookies()
        if result and result.get('cookies', {}) and result.get('sec_key', '') and result.get('sec_iv', ''):
            self.cookies = result.get('cookies')
            self.sec_key = result.get('sec_key')
            self.sec_iv = result.get('sec_iv')
        else:
            raise Exception('登录失败')
        logging.info('init result: %s', result)

    def process_request(self, request, spider):
        meta = request.meta
        if meta and self.sec_key and self.sec_iv and self.cookies:
            aes = AesCrypter(self.sec_key, self.sec_iv)

            timestamp = str(int(round(time.time())))
            if request.method == 'POST' and request.body:
                enc_msg = aes.encrypt(str(request.body, encoding='utf-8'))
                request._set_body(json.dumps({
                    'EncryptMsg': str(enc_msg, encoding='utf-8')
                }))
                hash = aes.hmac_sha1_sign(enc_msg, timestamp.encode())
            elif request.method == 'GET' and 'params' in meta and meta.get('params'):
                enc_msg = aes.encrypt(meta.get('params'))
                request._set_url(request.url + '?EncryptMsg=' + quote(str(enc_msg, encoding='utf-8')))
                hash = aes.hmac_sha1_sign(enc_msg, timestamp.encode())
            else:
                spider.logger.error('加密失败：<url=%s, meta=%s, params=%s>' % (request.url, meta, meta.get('params')))
                raise IgnoreRequest('加密失败')

            request.cookies = self.cookies
            request.meta['sec_key'] = self.sec_key
            request.meta['sec_iv'] = self.sec_iv
            request.headers['X-EncryptType'] = 'encrypt'
            request.headers['X-Timestamp'] = timestamp
            request.headers['X-IntegrityHash'] = hash
        else:
            spider.logger.error('加密参数异常：<url=%s, meta=%s>' % (request.url, meta))
            raise IgnoreRequest('加密参数异常')

    def process_response(self, request, response, spider):
        rs = json.loads(response.text)
        if response.text and rs and rs.get('Code') == 0 and 'Value' in rs:
            return response
        else:
            spider.logger.error('这里有异常：%s' % response.text)

        raise IgnoreRequest('响应异常：%s' % response.text)

    def process_exception(self, request, exception, spider):
        self.refresh_encrypt(request)
        spider.logger.error('validating error')

    def refresh_encrypt(self, request):
        # 加锁
        self._instance_lock.acquire()
        meta = request.meta
        if meta.get('sec_key') == self.sec_key or meta.get('sec_iv') == self.sec_iv:
            # 更新加密key
            launcher = Launcher()
            launcher.refresh_encrypt(self.cookies)
            if launcher.sec_iv and launcher.sec_key:
                self.sec_key = launcher.sec_key
                self.sec_iv = launcher.sec_iv
            else:
                logging.error("本次加密因子更新失败")
        # 释放锁
        self._instance_lock.release()
